package org.jvm.interpreter;

import org.jvm.JVM;
import org.jvm.instruction.base.*;
import org.jvm.rtda.thread.Thread;
import org.jvm.rtda.thread.*;

/**
 * 字节码解释器
 *
 * @author 海燕
 * @date 2023/1/29
 */
public class Interpret {

    /**
     * 线程解释器
     * 注意：线程栈并不一定从main或者Thread.run开始。起始栈高不一定为1。
     * 从虚拟机中直接发起JavaCall（例如隐式调用AppClassLoader），此时线程栈中可能有若干已经入栈的栈帧
     *
     * @param thread
     */
    public static void interpret(Thread thread) {
        //起始栈高
        int startStackSize = thread.getStack().getStack().size();
        ByteCodeReader reader = new ByteCodeReader();
        for (; thread.getStack().getStack().size() >= startStackSize; ) {
            //获取当前栈顶栈帧
            Frame frame = thread.getStack().top();
            int pc = frame.getNextPC();
            //我理解线程持有的程序计数器作用仅仅是供分支指令读取
            thread.setPc(pc);
            //获取对应的指令
            reader.reset(frame.getMethod().getCode(), pc);
            int opcode = reader.readUint8();
            Instruction instruction = InstructionFactory.newInstruction(opcode);
            if (JVM.log) {
                System.out.println(frame);
                System.out.println("  instruction:" + instruction.getClass().getSimpleName());
            }
            instruction.fetchOperands(reader);
            //读取指令标识和操作数后，记录程序计数器位置。如果接下来不执行分支指令的话，这里就是下次程序计数器开始的位置
            frame.setNextPC(reader.getPC());
            //指令执行。如果是分支指令会再改变帧中程序计数器的位置
            instruction.execute(frame);
        }
    }
}
